﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using IssueVision.Common;
using IssueVision.EntityModel;

namespace IssueVision.ViewModel
{
    [Export(ViewModelTypes.MyProfileViewModel, typeof(ViewModelBase))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class MyProfileViewModel : ViewModelBase
    {
        #region "Private Data Members"
        private IIssueVisionModel _issueVisionModel;
        #endregion "Private Data Members"

        #region "Constructor"
        [ImportingConstructor]
        public MyProfileViewModel(IIssueVisionModel issueVisionModel)
        {
            _issueVisionModel = issueVisionModel;

            // set up event handling
            _issueVisionModel.GetCurrentUserCompleted += _issueVisionModel_GetCurrentUserCompleted;
            _issueVisionModel.GetSecurityQuestionsCompleted += _issueVisionModel_GetSecurityQuestionsCompleted;
            _issueVisionModel.SaveChangesCompleted += _issueVisionModel_SaveChangesCompleted;
            _issueVisionModel.PropertyChanged += _issueVisionModel_PropertyChanged;

            // load current user
            _issueVisionModel.GetCurrentUserAsync();
            // load security questions
            _issueVisionModel.GetSecurityQuestionsAsync();
        }
        #endregion "Constructor"

        #region "ICleanup interface implementation"
        public override void Cleanup()
        {
            if (_issueVisionModel != null)
            {
                // unregister all events
                _issueVisionModel.GetCurrentUserCompleted -= _issueVisionModel_GetCurrentUserCompleted;
                _issueVisionModel.GetSecurityQuestionsCompleted -= _issueVisionModel_GetSecurityQuestionsCompleted;
                _issueVisionModel.SaveChangesCompleted -= _issueVisionModel_SaveChangesCompleted;
                _issueVisionModel.PropertyChanged -= _issueVisionModel_PropertyChanged;
                // set CurrentUser back to null
                CurrentUser = null;
                // set _issueVisionModel to null
                _issueVisionModel = null;
            }
            // set properties back to null
            SecurityQuestionEntries = null;
            // unregister any messages for this ViewModel
            base.Cleanup();
        }
        #endregion "ICleanup interface implementation"

        #region "Public Properties"

        public User CurrentUser
        {
            get
            {
                return _issueVisionModel != null ? _issueVisionModel.CurrentEditUser : null;
            }
            private set
            {
                if (_issueVisionModel != null)
                {
                    if (!ReferenceEquals(_issueVisionModel.CurrentEditUser, value))
                    {
                        // update CurrentEditUser on the model
                        _issueVisionModel.CurrentEditUser = value;
                        RaisePropertyChanged("CurrentUser");
                    }
                }
            }
        }

        private IEnumerable<SecurityQuestion> _securityQuestionEntries;

        public IEnumerable<SecurityQuestion> SecurityQuestionEntries
        {
            get { return _securityQuestionEntries; }
            private set
            {
                if (!ReferenceEquals(_securityQuestionEntries, value))
                {
                    _securityQuestionEntries = value;
                    RaisePropertyChanged("SecurityQuestionEntries");
                }
            }
        }

        #endregion "Public Properties"

        #region "Public Commands"

        private RelayCommand _submitChangeCommand;

        public RelayCommand SubmitChangeCommand
        {
            get
            {
                if (_submitChangeCommand == null)
                {
                    _submitChangeCommand = new RelayCommand(
                        () => OnSubmitChangeCommand(),
                        () => (_issueVisionModel != null) && (_issueVisionModel.HasChanges));
                }
                return _submitChangeCommand;
            }
        }

        private void OnSubmitChangeCommand()
        {
            try
            {
                if (!_issueVisionModel.IsBusy)
                {
                    if (CurrentUser != null)
                    {
                        if (CurrentUser.TryValidate())
                        {
                            // change is not from User Maintenance screen
                            CurrentUser.Settings.IsUserMaintenance = 0;
                            _issueVisionModel.SaveChangesAsync();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(ex);
            }
        }

        private RelayCommand _cancelChangeCommand;

        public RelayCommand CancelChangeCommand
        {
            get
            {
                if (_cancelChangeCommand == null)
                {
                    _cancelChangeCommand = new RelayCommand(
                        () => OnCancelChangeCommand(),
                        () => (_issueVisionModel != null) && (_issueVisionModel.HasChanges));
                }
                return _cancelChangeCommand;
            }
        }

        private void OnCancelChangeCommand()
        {
            try
            {
                if (!_issueVisionModel.IsBusy)
                {
                    // ask to confirm canceling the current user in edit
                    DialogMessage dialogMessage = new DialogMessage(
                        this,
                        CommonResources.CancelAnyChangesMessageBoxText,
                        s =>
                        {
                            if (s == MessageBoxResult.OK)
                            {
                                // if confirmed, cancel any change to CurrentUser
                                _issueVisionModel.RejectChanges();
                            }
                        })
                    {
                        Button = MessageBoxButton.OKCancel,
                        Caption = CommonResources.ConfirmMessageBoxCaption
                    };

                    AppMessages.PleaseConfirmMessage.Send(dialogMessage);
                }
            }
            catch (Exception ex)
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(ex);
            }
        }

        #endregion "Public Commands"

        #region "Private Methods"

        /// <summary>
        /// Event handler for GetCurrentUserCompleted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_GetCurrentUserCompleted(object sender, ResultArgs<User> e)
        {
            if (!e.HasError)
            {
                CurrentUser = e.Results;
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        /// <summary>
        /// Event handler for GetSecurityQuestionsCompleted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_GetSecurityQuestionsCompleted(object sender, ResultsArgs<SecurityQuestion> e)
        {
            if (!e.HasError)
            {
                SecurityQuestionEntries = e.Results.OrderBy(g => g.PasswordQuestion);
                // raise property changed for CurrentUser to reflect changes with SecurityQuestionEntries
                RaisePropertyChanged("CurrentUser");
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        /// <summary>
        /// Event handler for SaveChangesCompleted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_SaveChangesCompleted(object sender, ResultArgs<string> e)
        {
            if (!e.HasError)
            {
                // check whether there is any warning message returned
                if (!string.IsNullOrEmpty(e.Results))
                {
                    DialogMessage dialogMessage = new DialogMessage(
                        this,
                        e.Results,
                        null)
                    {
                        Button = MessageBoxButton.OK,
                        Caption = CommonResources.WarningMessageBoxCaption
                    };

                    AppMessages.StatusUpdateMessage.Send(dialogMessage);
                }
                else
                {
                    // load the current user again
                    _issueVisionModel.GetCurrentUserAsync();
                    // notify user of my profile saved successfully
                    DialogMessage dialogMessage = new DialogMessage(
                                this,
                                CommonResources.MyProfileSavedText,
                                null)
                    {
                        Button = MessageBoxButton.OK,
                        Caption = CommonResources.MyProfileSavedCaption
                    };

                    AppMessages.StatusUpdateMessage.Send(dialogMessage);
                }
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        /// <summary>
        /// Event handler for PropertyChanged
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName.Equals("HasChanges"))
            {
                SubmitChangeCommand.RaiseCanExecuteChanged();
                CancelChangeCommand.RaiseCanExecuteChanged();
            }
        }

        #endregion "Private Methods"
    }
}
